Matplotlib¶


Matplotlib 특징¶

  • 파이썬의 대표적인 과학 계산용 그래프 라이브러리
  • 선 그래프, 히스토그램, 산점도 등의 고품질 그래프 제공
  • 저수준 api를 사용한 다양한 시각화 기능 제공
  • 다양한 운영체제와 그래픽 백엔드에서 동작
In [201]:
import matplotlib as mpl 
import matplotlib.pyplot as plt
import pandas as pd 
import numpy as np 
mpl.__version__ 
Out[201]:
'3.2.2'
In [202]:
plt.style.use(['seaborn-notebook'])

라인 플롯(Line Plot)¶

  • 플롯(plot)은 그림(figure)와 축(axes)으로 구성
  • plt.Figure: 축과 그래픽, 텍스트, 레이블을 표시하는 모든 객체를 포함하는 컨테이너
  • plt.Axes: 눈금과 레이블이 있는 테두리 박스로 시각화를 형성하는 플롯 요소 포함
In [203]:
fig = plt.figure()
ax = plt.axes();  # 축 생성
In [204]:
fig = plt.figure() 
plt.plot([0, 0.2, 0.4, 0.6, 0.8, 1.0] * 5);
In [205]:
x = np.arange(0, 10, 0.01)

fig = plt.figure() 
plt.plot(x, np.sin(x))
plt.plot(x, np.cos(x));
In [206]:
plt.plot(np.random.randn(50).cumsum());

라인 스타일(Line Style)¶

  • '-' : 'solid'
  • '--' : 'dashded'
  • '-.-' : 'dashdot'
  • ':' : 'dotted'
In [207]:
plt.plot(np.random.randn(50).cumsum(), linestyle = 'solid')
plt.plot(np.random.randn(50).cumsum(), linestyle = 'dashed');
plt.plot(np.random.randn(50).cumsum(), linestyle = 'dashdot');
plt.plot(np.random.randn(50).cumsum(), linestyle = 'dotted');

색상 스타일(Color Style)¶

In [208]:
plt.plot(np.random.randn(50).cumsum(), color = 'saddlebrown')
plt.plot(np.random.randn(50).cumsum(), color = 'orangered')
plt.plot(np.random.randn(50).cumsum(), color = 'lightpink')
plt.plot(np.random.randn(50).cumsum(), color = 'orchid')
Out[208]:
[<matplotlib.lines.Line2D at 0x7f38df926b10>]
In [209]:
plt.plot(np.random.randn(50).cumsum(),'r--')
plt.plot(np.random.randn(50).cumsum(), 'g:')
plt.plot(np.random.randn(50).cumsum(), 'b.-');

플롯 축(Plot Axis)¶

In [210]:
plt.plot(np.random.randn(50));
plt.xlim(-1, 50) # x축 범위
plt.ylim(-5, 5); # y축 범위
In [211]:
plt.plot(np.random.randn(50))
plt.axis([-1, 50, -5, 5]);
In [212]:
plt.plot(np.random.randn(50));
plt.axis('tight');
In [213]:
plt.plot(np.random.randn(50));
plt.axis('equal');

플롯 레이블(Plot Label)¶

In [214]:
plt.plot(np.random.randn(50), label = 'A')
plt.plot(np.random.randn(50), label = 'B')
plt.plot(np.random.randn(50), label = 'C')
plt.title("title") # 제목
plt.xlabel("X") # X축 레이블
plt.ylabel("Y"); # Y축 레이블
plt.legend(); # 범례

폰트 관리자(Font Manager)¶

In [215]:
set([f.name for f in mpl.font_manager.fontManager.ttflist])
Out[215]:
{'DejaVu Sans',
 'DejaVu Sans Display',
 'DejaVu Sans Mono',
 'DejaVu Serif',
 'DejaVu Serif Display',
 'Humor Sans',
 'Liberation Mono',
 'Liberation Sans',
 'Liberation Sans Narrow',
 'Liberation Serif',
 'STIXGeneral',
 'STIXNonUnicode',
 'STIXSizeFiveSym',
 'STIXSizeFourSym',
 'STIXSizeOneSym',
 'STIXSizeThreeSym',
 'STIXSizeTwoSym',
 'cmb10',
 'cmex10',
 'cmmi10',
 'cmr10',
 'cmss10',
 'cmsy10',
 'cmtt10'}
In [216]:
font1 = {'family' : 'Dejavu Sans', 'size' : 24, 'color' : 'black'} 
font2 = {'family' : 'Liberation Mono', 'size' : 24, 'weight' : 'bold', 'color' : 'darkred'} 
font3 = {'family' : 'STIXGeneral', 'size' : 24, 'weight' : 'light', 'color' : 'blue'} 

plt.plot([1, 2, 3, 4, 5], [1, 2, 3, 4, 5])
plt.title('font1', fontdict = font1)
plt.xlabel("font2", fontdict = font2)
plt.ylabel("font3", fontdict = font3);

플롯 범례(Plot Legend)¶

In [217]:
fig, ax = plt.subplots()
ax.plot(np.random.randn(10), '-r', label = 'A')
ax.plot(np.random.randn(10), ':g', label = 'B')
ax.plot(np.random.randn(10), '--b', label = 'C')
ax.axis('equal')
ax.legend(loc = 'upper center', # 범례 위치
          frameon = False, # 범례상자를 안보이게
          ncol = 3); # 범례 표시를 3열로
In [218]:
ax.legend(fancybox = True, framealpha = 1, # 범례의 투명도 
          shadow = True, # 범례의 그림자
          borderpad=1) # 범례에 여백
fig 
Out[218]:
In [219]:
plt.figure(figsize = (8, 4))
x = np.linspace(0, 10, 1000)
y = np.cos(x[:, np.newaxis] * np.arange(0, 2, 0.2))
lines = plt.plot(x, y)
plt.legend(lines[:3], ['c1', 'c2', 'c3']);
In [220]:
plt.plot(x, y[:, 0], label = 'c1')
plt.plot(x, y[:, 1], label = 'c2')
plt.plot(x, y[:, 2], label = 'c3')
plt.plot(x, y[:, 3])
plt.legend(framealpha = 1, frameon = False, # True로 
           loc = 'upper right');
In [221]:
x = np.linspace(0, 20, 100)
I = np.cos(x) - np.cos(x[:, np.newaxis])

plt.imshow(I)
plt.colorbar();
In [222]:
plt.imshow(I, cmap = 'Blues')
plt.colorbar();

다중 플롯(Multiple Subplots)¶

In [223]:
ax1 = plt.axes()
ax2 = plt.axes([0.65, 0.5, 0.2, 0.3]);
In [224]:
for i in range(1,10):
  plt.subplot(3, 3, i)
  plt.text(0.5, 0.5, str((3, 3, i)), ha = 'center') # 다중 플롯이 생성됬으나 겹침
In [225]:
fig = plt.figure()
fig.subplots_adjust(hspace = 0.4, # 플롯간 세로 간격
                    wspace = 0.4) # 플롯간 가로 간격
for i in range(1,10):
  plt.subplot(3, 3, i)
  plt.text(0.5, 0.5, str((3, 3, i)), ha = 'center')
In [226]:
fig, ax = plt.subplots(3, 3, sharex = 'col', sharey = 'row')
In [227]:
for i in range(3):
  for j in range(3):
    ax[i, j].text(0.5, 0.5, str((i, j)), ha = 'center')
fig
Out[227]:
In [228]:
grid = plt.GridSpec(2, 3, wspace = 0.4, hspace = 0.4)

plt.subplot(grid[0, 0])
plt.subplot(grid[0, 1:])
plt.subplot(grid[1, :2])
plt.subplot(grid[1, 2])
Out[228]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f38dbe10f50>
In [229]:
plt.figure(figsize = (5, 6))

x = range(1, 21)
columns = [np.random.randn(20) * i for i in range(1, 7)]

i = 0
for c in columns:
  i += 1

  plt.subplot(3, 2, i)
  plt.plot(x, c, marker = 'o', linewidth = 1, label = c)
  plt.xlim(-1, 21)
  plt.ylim(c.min()-1, c.max()+1)

텍스트와 주석(Text and Annotation)¶

In [230]:
fig, ax = plt.subplots()
ax.axis([0, 10, 0, 10])
ax.text(3, 6, ". transData(3, 6)", transform = ax.transData) # 좌표에 텍스트 표시
ax.text(0.2, 0.4, ". transAxes(0.2, 0.4)", transform = ax.transAxes) # 각 축의 비율에 해당하는 위치
ax.text(0.2, 0.4, ". transFigure(0.2, 0.2)", transform = fig.transFigure); # 플롯 전체의 비율에 해당하는 위치
In [231]:
x = np.arange(1, 40)
y = x * 1.1
plt.scatter(x, y, marker = '.')
plt.axis('equal')
plt.annotate('interesting plot', 
             xy = (4, 5), # 화살표로 가리킬 위치
             xytext = (20, 10), # 텍스트의 위치
             arrowprops = dict(shrink = 0.05)); # 화살표의 두께
In [232]:
x1 = np.random.normal(30, 3, 100)
x2 = np.random.normal(30, 3, 100)
x3 = np.random.normal(30, 3, 100)

plt.plot(x1, label = 'p1')
plt.plot(x1, label = 'p2')
plt.plot(x1, label = 'p3')

plt.legend(bbox_to_anchor = (0., 1.02, 1., .102), loc = 0, ncol = 3,
           mode = 'extend', borderaxespad = 0.)
plt.annotate('important value', (30, 30), xytext = (50, 40), arrowprops = dict(arrowstyle = '->'))
plt.annotate('incorrect value', (30, 30), xytext = (30, 40), arrowprops = dict(arrowstyle = '->'));

눈금 맞춤(Customizing Ticks)¶

In [233]:
plt.axes(xscale = 'log', yscale = 'log');
In [234]:
ax = plt.axes()
ax.plot(np.random.randn(100).cumsum())

ax.yaxis.set_major_locator(plt.NullLocator()) # y축의 정보 삭제
ax.xaxis.set_major_formatter(plt.NullFormatter()) # x축의 눈금만 놔두고 삭제 
In [235]:
fig, ax = plt.subplots(3, 3, sharex = True, sharey = True); # X축과 Y축을 공유
In [236]:
for ax1 in ax.flat:
  ax1.xaxis.set_major_locator(plt.MaxNLocator(4))
  ax1.yaxis.set_major_locator(plt.MaxNLocator(4))
fig
Out[236]:
In [237]:
x = np.linspace(-np.pi, np.pi, 1000, endpoint = True)
y = np.sin(x)
plt.plot(x, y)

ax = plt.gca()
ax.spines['bottom'].set_position(('data', 0)) # 0을 기준으로 위쪽에 선
ax.spines['left'].set_position(('data', 0)) # 0을 기준으로 왼쪽에 선
ax.xaxis.set_ticks_position('bottom') # x축의 정보를 축 아래에
ax.yaxis.set_ticks_position('left') # y축의 정보를 축 왼쪽에
In [238]:
x = np.linspace(1, 10)
y = [10 ** el for el in x]
z = [2 * el for el in x]

fig = plt.figure(figsize = (10, 8))

ax1 = fig.add_subplot(2, 2, 1)
ax1.plot(x, y, '-y')
ax1.set_yscale('log')
ax1.set_title('Logarithmic plot of $ {10}^{x} $')
ax1.set_ylabel(r'$ {y} = {10}^{x} $')
plt.grid(b = True, which = 'both', axis = 'both')

ax1 = fig.add_subplot(2, 2, 2)
ax1.plot(x, y, '-r')
ax1.set_yscale('linear')
ax1.set_title('Linear plot of $ {10}^{x} $')
ax1.set_ylabel(r'$ {y} = {10}^{x} $')
plt.grid(b = True, which = 'both', axis = 'both')

ax1 = fig.add_subplot(2, 2, 3)
ax1.plot(x, z, '-g')
ax1.set_yscale('log')
ax1.set_title('Logarithmic plot of $ {2}^{x} $')
ax1.set_ylabel(r'$ {y} = {10}^{x} $')
plt.grid(b = True, which = 'both', axis = 'both')

ax1 = fig.add_subplot(2, 2, 4)
ax1.plot(x, z, '-b')
ax1.set_yscale('linear')
ax1.set_title('Linear plot of $ {2}^{x} $')
ax1.set_ylabel(r'$ {y} = {10}^{x} $')
plt.grid(b = True, which = 'both', axis = 'both')

스타일(Style)¶

In [239]:
fig = plt.figure(figsize = (10, 10))
x = range(1, 11)
columns = [np.random.randn(10) * i for i in range(1, 26)]

for n, v in enumerate(plt.style.available[1:]):
  plt.style.use(v)
  plt.subplot(5, 5, n + 1)
  plt.title(v)

  for c in columns:
    plt.plot(x, c, marker = '', color = 'royalblue', linewidth = 1, alpha = 0.1)
    plt.subplots_adjust(hspace = 0.5, wspace = 0.4)

플롯 종류¶

함수 설명
bar 막대 플롯(bar plot) 생성
barbs barbs의 2차원 필드 그리기
boxplot 상자 및 수염 플롯 생성
cohere x와 y의 일관성 시각화 그리기
contour 플롯 등고선
errorbar 오류 막대 그래프
hexbin 육각형 binning 플롯 생성
hist 히스토그램 플롯
imshow 축에 이미지 표시
pcolor 2차원 배열의 유사 플롯 생성
pcolormesh 사각 망사 그래프
pie 파이 차트 플롯
plot 플롯 라인 또는 마커
quiver 화살표의 2차원 필드 생성
sankey Sankey 흐름도 생성
scatter x대 y의 산점도 생성
stem 줄기 그래프 생성
streamplot 벡터 흐름의 스트림 라인 그리기

막대 플롯(Barplot)¶

In [240]:
height = [np.random.randn() * i for i in range(1, 6)]
names = ['A', 'B', 'C', 'D', 'E']
y_pos = np.arange(len(names)) 
plt.bar(y_pos, height) 
plt.xticks(y_pos, names, fontweight = 'bold')
plt.xlabel('group');
In [241]:
# 세로 막대그래프 
height = [np.random.randn() * i for i in range(1, 6)]
names = ['A', 'B', 'C', 'D', 'E']
y_pos = np.arange(len(names)) 
plt.barh(y_pos, height) 
plt.yticks(y_pos, names, fontweight = 'bold')
plt.ylabel('group');
In [242]:
bars1 = [12, 28, 1, 8, 22]
bars2 = [28, 7, 16, 4, 10]
bars3 = [25, 3, 23, 25, 17]
bars = np.add(bars1, bars2).tolist()

r = [0, 1, 2, 3, 4]
names = ['A', 'B', 'C', 'D', 'E']

plt.bar(r, bars1, color = 'royalblue', edgecolor = 'white')
plt.bar(r, bars2, bottom = bars1, color = 'skyblue', edgecolor = 'white')
plt.bar(r, bars3, bottom = bars2, color = 'lightblue', edgecolor = 'white')

plt.xlabel('groups', fontweight = 'bold')
plt.xticks(r, names, fontweight = 'bold');
In [243]:
bar_width = 0.25

bars1 = [14, 17, 9, 8, 7]
bars2 = [14, 6, 16, 4, 10]
bars3 = [21, 4, 23, 13, 17]

r1 = np.arange(len(bars1))
r2 = [x + bar_width for x in r1]
r3 = [x + bar_width for x in r2]

plt.bar(r1, bars1, color = 'royalblue', width = bar_width, edgecolor = 'white', label = 'r1')
plt.bar(r2, bars2, color = 'skyblue',  width = bar_width, edgecolor = 'white', label = 'r2')
plt.bar(r3, bars3, color = 'lightblue', width = bar_width, edgecolor = 'white', label = 'r3')

r = [0, 1, 2, 3, 4]
plt.xlabel('groups', fontweight = 'bold')
plt.xticks([r + bar_width for r in range(len(bars1))], ['A', 'B', 'C', 'D', 'E'])
plt.legend();

스템 플롯(Stem Plot)¶

In [244]:
x = np.linspace(0.1,  2 * np.pi, 41)
y = np.exp(np.sin(x))

plt.stem(x, y, linefmt = 'gray', bottom = 1, # Y기준 1의 위치에 bottom선
         use_line_collection = True)
Out[244]:
<StemContainer object of 3 artists>

박스플롯(Box Plot)¶

In [246]:
r1 = np.random.normal(loc = 0, scale = 0.5, size = 100)
r2 = np.random.normal(loc = 0.5, scale = 1, size = 100)
r3 = np.random.normal(loc = 1, scale = 1.5, size = 100)
r4 = np.random.normal(loc = 1.5, scale = 2, size = 100)
r5 = np.random.normal(loc = 2, scale = 2.5, size = 100)

fig, ax = plt.subplots(1, 1) 
ax.boxplot((r1, r2, r3, r4, r5))
ax.set_xticklabels(['r1', 'r2', 'r3', 'r4', 'r5']);

산점도(Scatter Plot)¶

In [270]:
plt.figure(figsize = (8, 4))
markers = ['.', ',', 'o', 'v', '^', '<', '>', '1', '2', '3', '4', 's', 'p', '*', 'h', 'H', '+', 'D', 'd']
for m in markers:
  plt.plot(np.random.rand(5), np.random.rand(5),  m, label = m)

plt.legend(loc = 'center right', ncol = 2)
plt.xlim(0, 1.5);
In [271]:
for i in range(9) :
  x = np.arange(1000)
  y = np.random.randn(1000).cumsum()
  plt.scatter(x, y, alpha = 0.2, cmap = 'viridis')

버블차트¶

In [277]:
x = np.random.randn(100)
y = np.random.randn(100)
colors = np.random.randn(100)
sizes = 1000 * np.random.randn(100)

plt.scatter(x, y, c = colors , s = sizes, alpha = 0.3, cmap = 'CMRmap')
plt.colorbar();
/usr/local/lib/python3.7/dist-packages/matplotlib/collections.py:885: RuntimeWarning: invalid value encountered in sqrt
  scale = np.sqrt(self._sizes) * dpi / 72.0 * self._factor
  • cmap: color map: https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html

x와 y의 일관성 차트(coherence)¶

In [281]:
plt.subplots_adjust(wspace = 1)

dt = 0.01
t = np.arange(0, 30, dt)
n1 = np.random.randn(len(t))
n2 = np.random.randn(len(t))
r = np.exp(-t/0.05)

c1 = np.convolve(n1, r, mode = 'same') * dt
c2 = np.convolve(n2, r, mode = 'same') * dt

s1 = 0.01 * np.sin(2 * np.pi * 10 * t) + c1
s2 = 0.01 * np.sin(2 * np.pi * 10 * t) + c2

plt.subplot(211)
plt.plot(t, s1, t, s2)
plt.xlim(0, 5)
plt.xlabel('time')
plt.ylabel('s1 & s2')
plt.grid(True)

plt.subplot(212)
plt.cohere(s1, s2 ** 2, 256, 1./dt)
plt.ylabel('coherence');

오차 막대(Error Bar)¶

  • 예상 측정 오차를 나타내는 데 사용
  • 오차 막대는 값의 불확실성을 나타냄
In [294]:
x = np.linspace(0, 20, 40)
dy = 1 
y = np.sin(x) + dy * np.random.randn(40)

plt.errorbar(x, y, yerr=dy, fmt = 's', color = 'darkblue', # 점의 색상
             ecolor = 'gray', # 선의 색상
             elinewidth = 5,  # 선의 두께
             capsize = 0);

2차원 유사 플롯, 히트맵 (pcolor/pcolormesh)¶

In [296]:
plt.pcolor(np.random.rand(20, 40), cmap = 'Reds');

히스토그램, 구간화, 밀도(Histograms, Binnings, and Density)¶

In [299]:
data = np.random.randn(10000)
plt.hist(data);
In [302]:
plt.hist(data, bins = 50, # 구간을 50개
         alpha = 0.5, # 투명도
         histtype = 'stepfilled',
         color = 'steelblue',
         edgecolor = 'navy');
In [305]:
x1 = np.random.normal(0, 1, 10000)
x2 = np.random.normal(-5, 3, 10000)
x3 = np.random.normal(5, 2, 10000)
d = dict(histtype = 'stepfilled', alpha = 0.3, bins = 50)

plt.hist(x1, **d)
plt.hist(x2, **d)
plt.hist(x3, **d);
In [307]:
x = np.random.normal(size = 50000)
y = x - np.random.normal(size = 50000) 

plt.hist2d(x, y, bins = 50, cmap = 'OrRd')
plt.colorbar();
In [308]:
x = np.random.normal(size = 50000)
y = x - np.random.normal(size = 50000) 

plt.hexbin(x, y, gridsize = 20, cmap = 'OrRd')
plt.colorbar();

밀도와 등고선 플롯(Density and Contour Plots)¶

In [309]:
a = np.arange(-1, 1, 0.1)
X, Y = np.meshgrid(a, a)

Z = np.sin(X * Y)
CS = plt.contour(X, Y, Z, levels = a) 
plt.clabel(CS, inline = 2)
plt.colorbar();
In [312]:
def f(x, y) :
  return (1 - (x ** 2 + y **2)) + np.exp(-y ** 2 / 2)

x = np.arange(-1.5, 1.5, 0.1)
y = np.arange(-1.5, 1.5, 0.1)

X, Y = np.meshgrid(x, y)
Z = f(X, Y)
N = np.arange(-1, 2, 0.2)

CS = plt.contour(Z, N, linewidth = 2, cmap = 'rainbow')
plt.clabel(CS, inline = True, fmt = '%1.1f')
plt.colorbar(CS);
/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:11: UserWarning: The following kwargs were not used by contour: 'linewidth'
  # This is added back by InteractiveShellApp.init_path()
In [314]:
plt.contourf(X, Y, Z)
plt.colorbar();
In [316]:
plt.imshow(Z, extent = [-1, 1, -1, 1], origin = 'lower', cmap = 'rainbow', alpha = 0.4);

스트림 플롯(Stream Plot)¶

In [318]:
Y, X = np.mgrid[0:5:100j, 0:5:100j]
U = X 
V = np.sin(Y) 
plt.streamplot(X, Y, U, V);

화살표 2차원 필드(quiver)¶

In [321]:
import sympy  

x, y = sympy.symbols('x y')
f = x**2 + y**2 + x*y - sympy.sin(x) * 4
fdx = sympy.diff(f, x)
fdy = sympy.diff(f, y) 

sample_size = 100 
xs, ys = np.meshgrid(np.linspace(-10, 10, sample_size), np.linspace(-10, 10, sample_size)) 

zs = [float(f.subs(x, xv).subs(y, yv)) for xv, yv in zip(xs.ravel(), ys.ravel())]
zs = np.array(zs).reshape(sample_size, sample_size) 

plt.contour(xs, ys, zs, 40, levels = np.logspace(-0.5, 2.0, 40), cmap = 'rainbow')

xs_q, ys_q = np.meshgrid(np.linspace(-10, 10, 10), np.linspace(-10, 10, 10))

xsg = [-float(fdx.subs(x, xv).subs(y, yv)) for xv, yv in zip(xs_q.ravel(), ys_q.ravel())]
ysg = [-float(fdx.subs(x, xv).subs(y, yv)) for xv, yv in zip(xs_q.ravel(), ys_q.ravel())]

plt.quiver(xs_q, ys_q, xsg, ysg, width = 0.005, scale = 500, color = 'black');

파이 차트(Pie Chart)¶

  • 원그래프, 파이차트는 전체에 대한 각 부분의 비율을 부채꼴 모양으로 나타낸 그래프
  • 각 부채꼴의 중심각이 전체에서 차지하는 비율을 나타내며, 비율을 한눈에 볼 수 있다는 장점
  • 전체적인 비율을 쉽게 파악할 수 있어서 언론사에서 통계 수치를 공개할 때 자주 활용
In [325]:
data = [10, 50, 30, 40, 60]
categories = ['C1', 'C2', 'C3', 'C4', 'C5'] 
plt.pie(data, labels = categories, autopct = '%0.1f%%')
plt.legend();
In [326]:
data = [10, 50, 30, 40, 60]
categories = ['C1', 'C2', 'C3', 'C4', 'C5'] 
explode = [0.1] * 5
plt.pie(data, explode = explode, labels = categories, autopct = '%0.1f%%')
plt.legend();

레이다 차트, 스타 차트(Radar Chart)¶

  • 어떤 측정 목표에 대한 평가항목이 여러 개일 때 항목 수에 따라 원을 같은 간격으로 나누고, 중심으로부터 일정 간격으로 동심으로 척도를 재는 칸을 나누어 각 평가항목의 정량화된 점수에 따라 그 위치에 점을 찍고 평가항목간 점을 이어 선으로 만들어 항목 간 균형을 한눈에 볼 수 있도록 해주는 도표
  • 여러 측정 목표를 함께 겹쳐 놓아 비교하기에도 편리 각 항목 간 비율뿐만 아니라 균형과 경향을 직관적으로 알 수 있어 편리
In [333]:
df = pd.DataFrame({
    'group' : ['A', 'B', 'C', 'D'],
    'var1' : [38, 1.5, 30, 4],
    'var2' : [29, 10, 9, 34],
    'var3' : [8, 39, 23, 24],
    'var4' : [7, 31, 33, 14],
    'var5' : [28, 15, 32, 14]
})

categories = list(df)[1:]
N = len(categories) 

angles = [n / float(N) * 2 * np.pi for n in range(N)]
angles += angles[:1]

ax = plt.subplot(111, polar = True)
ax.set_theta_offset(np.pi / 2)
ax.set_theta_direction(-1) 
ax.set_rlabel_position(0)
plt.xticks(angles[:-1], categories)
plt.yticks([10, 20, 30], ["10", "20", "30"], color = 'gray', size = 7)
plt.ylim(0, 40) 

values = df.loc[0].drop('group').values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth = 1, linestyle = 'solid', label = 'A') 
ax.fill(angles, values, 'b', alpha = 0.1)

values = df.loc[1].drop('group').values.flatten().tolist() 
values += values[:1]
ax.plot(angles, values, linewidth = 1, linestyle = 'solid', label = 'B')
ax.fill(angles, values, 'r', alpha = 0.1)

plt.legend(bbox_to_anchor = (0.1, 0.1));

생키 다이어그램(Sankey Diagram)¶

  • 흐름(Flow) 다이어그램의 한 종류로서 그 화살표의 너비로 흐름의 양을 비율적으로 보여줌
In [339]:
from matplotlib.sankey import Sankey

Sankey(flows = [0.20, 0.15, 0.25, -0.25, -0.25, -0.15, -0.60, -0.20],
       labels = ['Zero', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven'],
       orientations = [-1, -1, 0, 1, 1, 1, 0, -1]).finish(); # -1은 밑으로, 1은 위로, 0은 오른쪽

3차원 플로팅(Three-Dimensional Plotting)¶

In [340]:
from mpl_toolkits import mplot3d
In [341]:
fig = plt.figure()
ax = plt.axes(projection = '3d')
In [344]:
x = range(1, 101)
y = np.random.randn(100) * x
z = np.random.randn(100) * x

fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
ax.scatter(x, y, z, c = 'green', s = 60);
In [348]:
ax = plt.axes(projection = '3d') 

zline = np.linspace(0, 20, 1000)
xline = np.sin(zline)  
yline = np.cos(zline) 
ax.plot3D(xline, yline, zline, c = 'gray') 

zdata = 20 * np.random.random(100)  
xdata = np.sin(zdata) + 0.2 * np.random.randn(100)
ydata = np.cos(zdata) + 0.2 * np.random.randn(100) 
ax.scatter3D(xdata, ydata, zdata, c = zdata, cmap = 'Blues');
In [357]:
def f(x, y) :
  return np.cos(np.sqrt(x**2 + y**2))

l = np.linspace(-4, 4, 20) 
X, Y = np.meshgrid(l, l)
Z = f(X, Y)
In [363]:
fig = plt.figure()  
ax = plt.axes(projection = '3d')
ax.contour3D(X, Y, Z, 50, cmap = 'BuPu')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
/usr/local/lib/python3.7/dist-packages/mpl_toolkits/mplot3d/art3d.py:304: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
  self._segments3d = np.asanyarray(segments)
Out[363]:
Text(0.5, 0, 'z')
In [361]:
ax.view_init(60, 30)  
fig
Out[361]:
In [364]:
fig = plt.figure() 
ax = plt.axes(projection = '3d')  
ax.plot_wireframe(X, Y, Z, color = 'gray');
In [365]:
ax = plt.axes(projection = '3d')    
ax.plot_surface(X, Y, Z, rstride = 1, cstride = 1, 
                cmap = 'viridis', edgecolor = 'none')
Out[365]:
<mpl_toolkits.mplot3d.art3d.Poly3DCollection at 0x7f38d9748110>
In [368]:
r = np.linspace(0, 6, 20) 
theta = np.linspace(-0.8 * np.pi, 0.8 * np.pi, 40)
r, theta = np.meshgrid(r, theta) 

X = r * np.sin(theta)
Y = r * np.cos(theta)
Z = f(X, Y) 

ax = plt.axes(projection = '3d')
ax.plot_surface(X, Y, Z, rstride = 1, cstride = 1, 
                cmap = 'viridis', edgecolor = 'none')
Out[368]:
<mpl_toolkits.mplot3d.art3d.Poly3DCollection at 0x7f38da1cd490>
In [370]:
theta = 2 * np.pi * np.random.random(1000) 
r = 6 * np.random.random(1000)
X = np.ravel(r * np.sin(theta))
Y = np.ravel(r * np.cos(theta)) 
Z = f(X, Y)

ax = plt.axes(projection = '3d')  
ax.scatter(X, Y, Z, c = Z, cmap = 'viridis', linewidth = 0.5);
In [373]:
ax = plt.axes(projection = '3d')  
ax.plot_trisurf(X, Y, Z, cmap = 'viridis', edgecolor = 'none');

참고문헌¶

  • Matplotlib, https://matplotlib.org/
  • Igor Milovanovi, "Python Data Visualization Cookbook", Packt
  • Jake VanderPlas, "Python Data Science Handbook", O'Reilly
  • Wes Mckinney, "Python for Data Analysis", O'Reilly